package cn.micro.eye.service.impl;

import cn.micro.eye.commons.validate.IEnum;
import cn.micro.eye.commons.auth.AuthContext;
import cn.micro.eye.commons.entity.MicroEntity;
import cn.micro.eye.commons.exception.MicroBadRequestException;
import cn.micro.eye.commons.exception.MicroErrorException;
import cn.micro.eye.commons.mybatis.extension.MicroServiceImpl;
import cn.micro.eye.commons.utils.*;
import cn.micro.eye.convert.MemberConvert;
import cn.micro.eye.entity.*;
import cn.micro.eye.mapper.*;
import cn.micro.eye.model.add.MemberAdd;
import cn.micro.eye.model.dto.MemberCategoryCount;
import cn.micro.eye.model.dto.MemberPageDTO;
import cn.micro.eye.model.edit.MemberEdit;
import cn.micro.eye.model.query.MemberPageQuery;
import cn.micro.eye.model.vo.MemberInfoVO;
import cn.micro.eye.model.vo.MemberPageVO;
import cn.micro.eye.model.vo.MemberSearchVO;
import cn.micro.eye.service.IAccountService;
import cn.micro.eye.service.IMemberService;
import cn.micro.eye.type.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * <p>
 * 用户基础信息 服务实现类
 * </p>
 *
 * @author lry
 * @since 2018-09-11
 */
@Service
public class MemberServiceImpl extends MicroServiceImpl<IMemberMapper, Member> implements IMemberService {

    private static final String HEAD_IMAGE_PREFIX = "http://oss.eyehh.com/head-default/";
    private static final List<String> HEAD_IMAGES = Arrays.asList(
            "01.png", "02.png", "03.png", "04.png", "05.png", "06.png", "07.png", "08.png", "09.png");

    private static final String DEFAULT_PASSWORD = "123456";

    @Resource
    private IAccountMapper accountMapper;
    @Resource
    private IMemberRoleMapper memberRoleMapper;

    @Resource
    private IAccountService accountService;

    @Override
    public MemberInfoVO info() {
        Member member = baseMapper.selectById(AuthContext.getUserId());
        if (member == null) {
            throw new MicroBadRequestException("Not Found Member");
        }

        // 用户信息
        MemberInfoVO memberInfoVO = MemberConvert.INSTANCE.copyMemberInfo(member);
        memberInfoVO.setMemberId(member.getId());
        memberInfoVO.setMemberName(member.getName());
        memberInfoVO.setMemberCategory(member.getCategory());

        // 权限角色
        memberInfoVO.setRoles(memberRoleMapper.selectRoleCodesByMemberId(member.getId()));
        return memberInfoVO;
    }

    @Override
    public Long memberCount() {
        List<String> authorities = AuthContext.getAuthorities();
        if (authorities.contains(RoleEnum.ROLE_SUPER_ADMIN.toString())) {
            return Long.valueOf(baseMapper.selectCount(new QueryWrapper<>()));
        } else if (authorities.contains(RoleEnum.ROLE_LESSEE.toString())) {
            return baseMapper.countSearchOrganizationPage(new MemberPageDTO());
        }

        return 0L;
    }

    @Override
    public List<MemberCategoryCount> categoryCount() {
        List<MemberCategoryCount> memberCategoryCountList = baseMapper.countCategory();
        for (MemberCategoryCount m : memberCategoryCountList) {
            m.setName(IEnum.getEnumTitle(MemberCategoryEnum.class, m.getCategory()));
        }

        return memberCategoryCountList;
    }

    @Override
    public Page<MemberPageVO> searchPage(MemberPageQuery query) {
        Page<MemberPageVO> page = new Page<>(query.getCurrent(), query.getSize());
        MemberPageDTO memberPageDTO = MemberConvert.INSTANCE.copy(query);
        memberPageDTO.setCurrent((memberPageDTO.getCurrent() - 1) * memberPageDTO.getSize());

        List<MemberPageVO> pageList;
        List<String> authorities = AuthContext.getAuthorities();
        if (authorities.contains(RoleEnum.ROLE_SUPER_ADMIN.toString())) {
            pageList = baseMapper.searchPage(memberPageDTO);
            page.setTotal(baseMapper.countSearchPage(memberPageDTO));
        } else {
            pageList = baseMapper.searchOrganizationPage(memberPageDTO);
            page.setTotal(baseMapper.countSearchOrganizationPage(memberPageDTO));
        }

        page.setDesc(MicroEntity.UPDATED_AT_FIELD);
        page.setRecords(pageList);
        if (pageList != null) {
            for (MemberPageVO memberPageVO : pageList) {
                memberPageVO.setCategoryName(IEnum.getEnumTitle(MemberCategoryEnum.class, memberPageVO.getCategory()));
            }
        }

        return page;
    }

    @Override
    public MemberPageVO get(Long id) {
        Member member = baseMapper.selectById(id);
        if (member == null) {
            throw new MicroBadRequestException("没有找到该记录");
        }

        return MemberConvert.INSTANCE.toVO(member);
    }

    @Override
    public Boolean delete(List<Long> ids) {
        List<Member> memberList = new ArrayList<>();
        for (Long id : ids) {
            Member member = new Member();
            member.setId(id);
            member.setDeleted(DeletedEnum.DELETED.getValue());
            memberList.add(member);
        }

        if (this.updateBatchById(memberList)) {
            Account deleteAccount = new Account();
            deleteAccount.setDeleted(DeletedEnum.DELETED.getValue());

            QueryWrapper<Account> deleteEntityWrapper = new QueryWrapper<>();
            deleteEntityWrapper.in(Account.MEMBER_ID_FIELD, ids);
            return accountService.update(deleteAccount, deleteEntityWrapper);
        }

        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean edit(MemberEdit edit) {
        Member editMember = MemberConvert.INSTANCE.toEntityEdit(edit);
        editMember.setId(AuthContext.getUserId());
        int flag = baseMapper.updateById(editMember);
        if (flag < 1) {
            throw new MicroErrorException("信息修改失败");
        }

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(MemberAdd memberAdd) throws Exception {
        if (StringUtils.isBlank(memberAdd.getMobile()) &&
                StringUtils.isBlank(memberAdd.getIdCard()) &&
                StringUtils.isBlank(memberAdd.getEmail())) {
            throw new MicroBadRequestException("手机和身份证和邮箱不能同时为空");
        }
        if (StringUtils.isNotBlank(memberAdd.getMobile())) {
            if (!TelUtils.validateMobile(memberAdd.getMobile())) {
                throw new MicroBadRequestException("非法手机号码");
            }
            QueryWrapper<Member> mobileEntityWrapper = new QueryWrapper<>();
            mobileEntityWrapper.eq(Member.MOBILE_FIELD, memberAdd.getMobile());
            if (baseMapper.selectCount(mobileEntityWrapper) > 0) {
                throw new MicroBadRequestException("手机号已存在");
            }
        }
        if (StringUtils.isNotBlank(memberAdd.getIdCard())) {
            if (!IdCardUtils.isValidate18IdCard(memberAdd.getIdCard())) {
                throw new MicroBadRequestException("非法身份证号码");
            }
            QueryWrapper<Member> idCardEntityWrapper = new QueryWrapper<>();
            idCardEntityWrapper.eq(Member.ID_CARD_FIELD, memberAdd.getIdCard());
            if (baseMapper.selectCount(idCardEntityWrapper) > 0) {
                throw new MicroBadRequestException("身份证号码已存在");
            }
        }
        if (StringUtils.isNotBlank(memberAdd.getEmail())) {
            if (!EmailUtils.validate(memberAdd.getEmail())) {
                throw new MicroBadRequestException("非法邮箱地址");
            }
            QueryWrapper<Member> idCardEntityWrapper = new QueryWrapper<>();
            idCardEntityWrapper.eq(Member.EMAIL_FIELD, memberAdd.getEmail());
            if (baseMapper.selectCount(idCardEntityWrapper) > 0) {
                throw new MicroBadRequestException("邮箱地址已存在");
            }
        }

        Member member = MemberConvert.INSTANCE.toEntity(memberAdd);
        member.setHeadImgUrl(this.randomHeadImgUrl());
        member.setCategory(MemberCategoryEnum.ORDINARY.getValue());
        member.setResource(MemberResourceEnum.ORG_ADD.getValue());
        member.setPassword(AESUtils.encode(DEFAULT_PASSWORD));
        if (StringUtils.isNotBlank(memberAdd.getIdCard())) {
            IdCardUtils.IdCardInfo extractor = IdCardUtils.parse(memberAdd.getIdCard());
            member.setAge(extractor.getAge());
            member.setBirth(extractor.getBirthday());
        }

        int flag = baseMapper.insert(member);
        if (flag < 1) {
            throw new MicroErrorException("用户添加失败");
        }

        if (StringUtils.isNotBlank(memberAdd.getMobile())) {
            Account insertAccount = new Account();
            insertAccount.setOpenId(memberAdd.getMobile());
            insertAccount.setRegisterType(RegisterTypeEnum.PHONE.getValue());
            insertAccount.setMemberId(member.getId());
            insertAccount.setRegisterIp(IPUtils.getIPAddress());
            int flagAccount = accountMapper.insert(insertAccount);
            if (flagAccount < 1) {
                throw new MicroErrorException("添加手机号登录方式失败");
            }
        }
        if (StringUtils.isNotBlank(memberAdd.getIdCard())) {
            Account insertAccount = new Account();
            insertAccount.setOpenId(memberAdd.getIdCard());
            insertAccount.setRegisterType(RegisterTypeEnum.ID_CARD.getValue());
            insertAccount.setMemberId(member.getId());
            insertAccount.setRegisterIp(IPUtils.getIPAddress());
            int flagAccount = accountMapper.insert(insertAccount);
            if (flagAccount < 1) {
                throw new MicroErrorException("添加身份证登录方式失败");
            }
        }
        if (StringUtils.isNotBlank(memberAdd.getEmail())) {
            Account insertAccount = new Account();
            insertAccount.setOpenId(memberAdd.getEmail());
            insertAccount.setRegisterType(RegisterTypeEnum.EMAIL.getValue());
            insertAccount.setMemberId(member.getId());
            insertAccount.setRegisterIp(IPUtils.getIPAddress());
            int flagAccount = accountMapper.insert(insertAccount);
            if (flagAccount < 1) {
                throw new MicroErrorException("添加邮箱登录方式失败");
            }
        }

        // 分配角色
        MemberRole memberRole = new MemberRole();
        memberRole.setRoleId((long) RoleEnum.ROLE_USER.getValue());
        memberRole.setMemberId(member.getId());
        int rsFlag = memberRoleMapper.insert(memberRole);
        if (rsFlag < 1) {
            throw new MicroErrorException("用户角色分配失败");
        }

        List<String> authorities = AuthContext.getAuthorities();
        if (CollectionUtils.isEmpty(authorities)) {
            throw new MicroBadRequestException("当前用户角色未分配角色");
        }


        return true;
    }

    @Override
    public List<MemberSearchVO> search(String openId) {
        if (StringUtils.isBlank(openId)) {
            return Collections.emptyList();
        }

        QueryWrapper<Member> entityWrapper = new QueryWrapper<>();
        entityWrapper.like(Member.MOBILE_FIELD, openId)
                .or().like(Member.ID_CARD_FIELD, openId)
                .or().like(Member.EMAIL_FIELD, openId)
                .last("limit 10");
        List<Member> memberList = baseMapper.selectList(entityWrapper);
        if (CollectionUtils.isNotEmpty(memberList)) {
            List<MemberSearchVO> memberSearchVOList = new ArrayList<>();
            for (Member member : memberList) {
                MemberSearchVO vo = new MemberSearchVO();
                vo.setMemberId(member.getId());
                vo.setMemberName(member.getName());
                vo.setMobile(TelUtils.hideMobile(member.getMobile()));
                vo.setIdCard(IdCardUtils.hide(member.getIdCard()));
                memberSearchVOList.add(vo);
            }

            return memberSearchVOList;
        }

        return Collections.emptyList();
    }

    @Override
    public String randomHeadImgUrl() {
        return HEAD_IMAGE_PREFIX + HEAD_IMAGES.get(new Random().nextInt(HEAD_IMAGES.size()));
    }

}
